package communication

import (
	"encoding/json"
	"fmt"
	"log"
)

type AsyncClient struct {
	ClientComm
	cmd string
}

func (client *AsyncClient) Connect(cmd string) {
	client.cmd = cmd
	log.Printf("异步客户端%s正在连接服务器", cmd)
	client.ClientComm.init(Host, AsyncPort)
	log.Printf("异步客户端%s连接服务器成功", cmd)
	client.Send(cmd)
}

func (client *AsyncClient) Close() {
	client.ClientComm.Close()
	log.Printf("异步客户端%s已关闭连接", client.cmd)
}

func (client *AsyncClient) messageEncode(obj interface{}) []byte {
	switch obj.(type) {
	case string:
		return []byte(fmt.Sprintf("str:%s", obj))
	case []byte:
		return append([]byte("byte:"), obj.([]byte)...)
	case map[string]interface{}:
		res, err := json.Marshal(obj)
		if err != nil {
			panic(err)
		}
		return append([]byte("json:"), res...)
	default:
		panic("不支持发送的类型")
	}
}

func (client *AsyncClient) messageDecode(msg []byte) interface{} {
	var type_ string
	var val []byte
	for i, c := range msg {
		if c == ':' {
			type_ = string(msg[:i])
			val = msg[i+1:]
		}
	}
	switch type_ {
	case "str":
		return string(val)
	case "byte":
		return val
	case "json":
		var res interface{}
		err := json.Unmarshal(val, res)
		if err != nil {
			panic(err)
		}
		return res
	default:
		panic("不支持接受的类型")
	}
}

func (client *AsyncClient) Send(obj interface{}) interface{} {
	msg := client.messageEncode(obj)
	client.sendBytes(msg)
	ret := client.recvBytes()
	return client.messageDecode(ret)
}

func WithAsyncClient(cmd string, fun func(AsyncClient)) {
	client := AsyncClient{}
	defer client.Close()
	defer func() {
		if err := recover(); err != nil {
			log.Printf("异步客户端出错：%s", err)
		}
	}()
	client.Connect(cmd)
	fun(client)
}
